package Tools::IPCheck;
use strict;
use warnings;

use Encode;
use LWP::UserAgent;
use HTTP::Request::Common;

require Exporter;

our (@ISA, @EXPORT);
@ISA = qw/Exporter/;

@EXPORT = qw/check_ip get_ip check_ip_from_ip138 check_city/;


#得到用得默认得IP
sub get_ip {

    return $ENV{'REMOTE_ADDR'};    
}

sub check_ip_from_ip138 {
    my $ip = shift;

    my $url = 'http://www.ip138.com/ips8.asp';

    my $browser = LWP::UserAgent->new;
    $browser->agent('Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.5)'.
        ' Gecko/20091109 Ubuntu/9.04 (jaunty) Shiretoko/3.5.5');
    
    #增加浏览器的header
    $browser->default_header(
        'Accept'=>'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8');
    $browser->default_header(
        'Accept-Language'=>'zh-cn,en-us;q=0.7,en;q=0.3');
    $browser->default_header(
        'Accept-Charset'=>'UTF-8,*');
    $browser->default_header(
        'Accept-Encoding'=>'gzip,deflate');

    push @{ $browser->requests_redirectable }, 'POST';

    #设定cookie
    $browser->cookie_jar({});
    
    my $request = POST($url, [
        ip=>$ip,
        action=>2,
    ]);

    my $res = $browser->request($request);
    if ( $res->code == 200 ) {

        my $content = decode('cp936', $res->content);

        my $cn_var1 = decode('utf-8', '本站主数据：');

        my ($main_data, $sub_data);

        if ( $content =~ /<li>$cn_var1(.*?)<\/li>/g ) {
            $main_data =  $1;
        } else {
            $main_data = '无结果';
        }


        $cn_var1 = decode('utf-8', '参考数据一：');

        if ( $content =~ /<li>$cn_var1(.*?)<\/li>/g ) {
            $sub_data = $1;
        } else {
            $sub_data = '无结果';
        }

        return ($main_data, $sub_data);
    }
}


sub check_ip {
    my $ip = shift;
    my $ip_db = shift;

    my($ip_begin, $ip_end, $ip_data1, 
        $ip_data2, $data_seek, $ip_flag, $ip_addr1, $ip_addr2 );

    if ( !$ip ) {
        return '';
    }

    my @ip = split /\./, $ip;

    my $ip_num = $ip[0] * 16777216 + $ip[1] * 65536 +
        $ip[2] * 256 + $ip[3];

    open FH, "<$ip_db" or die "can't open the ip database file:$!\n";
    binmode FH;

    sysread(FH, $ip_begin, 4);
    sysread(FH, $ip_end, 4);
    $ip_begin = unpack("L", $ip_begin);
    $ip_end = unpack("L", $ip_end);

    my $ip_all_num = ( $ip_end - $ip_begin ) / 7 + 1;

    my $begin_num = 0;
    my $end_num = $ip_all_num;

    Bgn:
    my $middle = int(($end_num + $begin_num ) / 2 );

    seek(FH, $ip_begin + 7 * $middle, 0);
    read(FH, $ip_data1, 4);
    my $ip1_num = unpack("L", $ip_data1);
    if ( $ip1_num > $ip_num ) {
        $end_num = $middle;
        goto Bgn;
    }

    read(FH, $data_seek, 3);
    $data_seek = unpack("L", $data_seek."\0");
    seek(FH, $data_seek, 0);
    read(FH, $ip_data2, 4);

    my $ip2_num = unpack("L", $ip_data2);
    if ( $ip2_num < $ip_num ) {
        goto nd if ( $middle == $begin_num );
        $begin_num = $middle;
        goto Bgn;
    }

    $/ = "\0";

    read(FH, $ip_flag, 1);

    if ( $ip_flag eq "\1" ) {
        my $ip_seek;
        read(FH, $ip_seek, 3);
        $ip_seek = unpack("L", $ip_seek."\0");
        seek(FH, $ip_seek, 0);
        read(FH, $ip_flag, 1);
    }

    if ( $ip_flag eq "\2" ) {
        my $addr_seek;
        read(FH, $addr_seek, 3);
        read(FH, $ip_flag, 1);

        if ( $ip_flag eq "\2" ) {
            my $addr_seek2;
            read(FH, $addr_seek2, 3);
            $addr_seek2 = unpack("L", $addr_seek2."\0");
            seek(FH, $addr_seek2, 0);
        } else {
            seek(FH, -1, 1); 
        }
        $ip_addr2 = <FH>;
        $addr_seek = unpack("L", $addr_seek."\0");
        seek(FH, $addr_seek, 0);
        $ip_addr1 = <FH>;
    } else {
        seek(FH, -1, 1);
        $ip_addr1 = <FH>;
        read(FH, $ip_flag, 1);
        if ( $ip_flag eq "\2" ) {
            my $addr_seek2;
            read(FH, $addr_seek2, 3);
            $addr_seek2 = unpack("L", $addr_seek2."\0");
            seek(FH, $addr_seek2, 0);
        } else {
            seek(FH, -1, 1);
        }
        $ip_addr2 = <FH>;
    }

    nd:
    chomp($ip_addr1, $ip_addr2);
    $/ = "\n";
    close FH;

    $ip_addr2 = "" if ($ip_addr2 =~ /http/i );

    my $ip_addr = decode('cp936', "$ip_addr1 $ip_addr2");
    $ip_addr =~ s/CZ88\.NET//isg;

    $ip_addr = "未知地区" if ( $ip_addr =~ /未知|http/i || $ip_addr eq "" );

    return $ip_addr;

}

sub  check_city {
    my $ip = shift;
    my $ip_db = shift;

    my($ip_begin, $ip_end, $ip_data1, 
        $ip_data2, $data_seek, $ip_flag, $ip_addr1, $ip_addr2);

    if ( !$ip ) {
        return '';
    }

    my @ip = split /\./, $ip;

    my $ip_num = $ip[0] * 16777216 + $ip[1] * 65536 +
        $ip[2] * 256 + $ip[3];

    open FH, "<$ip_db" or die "can't open the ip database file:$!\n";
    binmode FH;

    sysread(FH, $ip_begin, 4);
    sysread(FH, $ip_end, 4);
    $ip_begin = unpack("L", $ip_begin);
    $ip_end = unpack("L", $ip_end);

    my $ip_all_num = ( $ip_end - $ip_begin ) / 7 + 1;

    my $begin_num = 0;
    my $end_num = $ip_all_num;

    Bgn:
    my $middle = int(($end_num + $begin_num ) / 2 );

    seek(FH, $ip_begin + 7 * $middle, 0);
    read(FH, $ip_data1, 4);
    my $ip1_num = unpack("L", $ip_data1);
    if ( $ip1_num > $ip_num ) {
        $end_num = $middle;
        goto Bgn;
    }

    read(FH, $data_seek, 3);
    $data_seek = unpack("L", $data_seek."\0");
    seek(FH, $data_seek, 0);
    read(FH, $ip_data2, 4);

    my $ip2_num = unpack("L", $ip_data2);
    if ( $ip2_num < $ip_num ) {
        goto nd if ( $middle == $begin_num );
        $begin_num = $middle;
        goto Bgn;
    }

    $/ = "\0";

    read(FH, $ip_flag, 1);

    if ( $ip_flag eq "\1" ) {
        my $ip_seek;
        read(FH, $ip_seek, 3);
        $ip_seek = unpack("L", $ip_seek."\0");
        seek(FH, $ip_seek, 0);
        read(FH, $ip_flag, 1);
    }

    if ( $ip_flag eq "\2" ) {
        my $addr_seek;
        read(FH, $addr_seek, 3);
        read(FH, $ip_flag, 1);

        if ( $ip_flag eq "\2" ) {
            my $addr_seek2;
            read(FH, $addr_seek2, 3);
            $addr_seek2 = unpack("L", $addr_seek2."\0");
            seek(FH, $addr_seek2, 0);
        } else {
            seek(FH, -1, 1); 
        }
        $ip_addr2 = <FH>;
        $addr_seek = unpack("L", $addr_seek."\0");
        seek(FH, $addr_seek, 0);
        $ip_addr1 = <FH>;
    } else {
        seek(FH, -1, 1);
        $ip_addr1 = <FH>;
        read(FH, $ip_flag, 1);
        if ( $ip_flag eq "\2" ) {
            my $addr_seek2;
            read(FH, $addr_seek2, 3);
            $addr_seek2 = unpack("L", $addr_seek2."\0");
            seek(FH, $addr_seek2, 0);
        } else {
            seek(FH, -1, 1);
        }
        $ip_addr2 = <FH>;
    }

    nd:
    chomp($ip_addr1, $ip_addr2);
    $/ = "\n";
    close FH;

    $ip_addr2 = "" if ($ip_addr2 =~ /http/i );

    my $ip_addr = decode('cp936', "$ip_addr1 $ip_addr2");
    $ip_addr =~ s/CZ88\.NET//isg;

    $ip_addr = "未知地区" if ( $ip_addr =~ /未知|http/i || $ip_addr eq "" );

    return decode('cp936', $ip_addr1);
}

1;
